package control

import (
	"JVM/Jvmgo/GoToJVM/instructions/base"
	"JVM/Jvmgo/GoToJVM/runtimeData"
)

/*
	ireturn: 从当前方法返回int
	lreturn: 从当前方法返回long
	dreturn: 从当前方法返回double
	areturn: 从当前方法返回对象引用
	freturn: 从当前方法返回float
	return: 从当前方法返回void
*/

type RETURN struct {
	base.NoOperandsInstruction
}
type IRETURN struct {
	base.NoOperandsInstruction
}
type LRETURN struct {
	base.NoOperandsInstruction
}
type DRETURN struct {
	base.NoOperandsInstruction
}
type FRETURN struct {
	base.NoOperandsInstruction
}
type ARETURN struct {
	base.NoOperandsInstruction
}

// 返回为空，那么就弹出当前帧表示线程结束
func (self *RETURN) Execute(frame *runtimeData.Frame) {
	frame.Thread().PopFrame()
}

// 从当前方法帧获取栈顶的返回值，并将其压入到调用者帧
func (self *IRETURN) Execute(frame *runtimeData.Frame) {
	thread := frame.Thread()
	currentFrame := thread.PopFrame()
	invokerFrame := thread.TopFrame()
	returnVal := currentFrame.OperandStack().PopInt()
	invokerFrame.OperandStack().PushInt(returnVal)
}

// Long与int同理
func (self *LRETURN) Execute(frame *runtimeData.Frame) {
	thread := frame.Thread()
	currentFrame := thread.PopFrame()
	invokerFrame := thread.TopFrame()
	returnVal := currentFrame.OperandStack().PopLong()
	invokerFrame.OperandStack().PushLong(returnVal)
}

func (self *DRETURN) Execute(frame *runtimeData.Frame) {
	thread := frame.Thread()
	currentFrame := thread.PopFrame()
	invokerFrame := thread.TopFrame()
	returnVal := currentFrame.OperandStack().PopDouble()
	invokerFrame.OperandStack().PushDouble(returnVal)
}

func (self *FRETURN) Execute(frame *runtimeData.Frame) {
	thread := frame.Thread()
	currentFrame := thread.PopFrame()
	invokerFrame := thread.TopFrame()
	returnVal := currentFrame.OperandStack().PopFloat()
	invokerFrame.OperandStack().PushFloat(returnVal)
}

func (self *ARETURN) Execute(frame *runtimeData.Frame) {
	thread := frame.Thread()
	currentFrame := thread.PopFrame()
	invokerFrame := thread.TopFrame()
	returnVal := currentFrame.OperandStack().PopRef()
	if returnVal != nil {
		returnVal.AddRef()
	}
	invokerFrame.OperandStack().PushRef(returnVal)
}
